home *** CD-ROM | disk | FTP | other *** search
/ JCSM Shareware Collection 1996 September / JCSM Shareware Collection (JCS Distribution) (September 1996).ISO / uother__ / 11780b01.ziv / EMS.PAS < prev    next >
Pascal/Delphi Source File  |  1994-01-01  |  16KB  |  444 lines

  1. program Ems_Test;
  2. { *************************************************************
  3.   * This program shows you how to use the basic functions of  *
  4.   * the LIM Expanded Memory Specification. Since it does not  *
  5.   * use any of the LIM EMS 4.0 function calls, you can also   *
  6.   * use it on systems with EMS versions less than 4.0         *
  7.   ************************************************************* }
  8.  
  9. { Written by:
  10.     Peter Immarco.
  11.     Thought Dynamics
  12.     Manhattan Beach, CA
  13.     Compuserve ID# 73770,123
  14.      *** Public Domain ***
  15.  
  16.   Used by permission of the author.
  17. }
  18.  
  19. { This program does the following:
  20.   +------------------------------------------------------------+
  21.   | * Makes sure the LIM Expanded Memory Manager (EMM) has     |
  22.   |   been installed in memory                                 |
  23.   | * Displays the version number of the EMM present in memory |
  24.   | * Determines if there are enough pages (16k blocks) of     |
  25.   |   memory for our test program's usage. It then displays    |
  26.   |   the total number of EMS pages present in the system,     |
  27.   |   and how many are available for our usage                 |
  28.   | * Requests the desired number of pages from the EMM        |
  29.   | * Maps a logical page onto one of the physical pages given |
  30.   |   to us                                                    |
  31.   | * Displays the base address of our EMS memory page frame   |
  32.   | * Performs a simple read/write test on the EMS memory given|
  33.   |   to us                                                    |
  34.   | * Returns the EMS memory given to us back to the EMM, and  |
  35.   |   exits                                                    |
  36.   +------------------------------------------------------------|}
  37.  
  38.  
  39. { All the calls are structured to return the result or error
  40.   code of the Expanded Memory function performed as an integer.
  41.   If the error code is not zero, which means the call failed,
  42.   a simple error procedure is called and the program terminates.}
  43.  
  44. uses Crt, Dos;
  45.  
  46. Type
  47.   ST3  = string[3];
  48.   ST80 = string[80];
  49.   ST5 = string[5];
  50.  
  51. Const
  52.   EMM_INT                   = $67;
  53.   DOS_Int                   = $21;
  54.   GET_PAGE_FRAME            = $41;
  55.   GET_UNALLOCATED_PAGE_COUNT= $42;
  56.   ALLOCATE_PAGES            = $43;
  57.   MAP_PAGES                 = $44;
  58.   DEALLOCATE_PAGES          = $45;
  59.   GET_VERSION               = $46;
  60.  
  61.   STATUS_OK                 = 0;
  62.  
  63.   { We'll say we need 1 EMS page for our application }
  64.   APPLICATION_PAGE_COUNT    = 10;
  65.  
  66. Var
  67.   Regs: Registers;
  68.   Emm_Handle,
  69.   Page_Frame_Base_Address,
  70.   Pages_Needed,
  71.   Physical_Page,
  72.   Logical_Page,
  73.   Offset,
  74.   Error_Code,
  75.   Pages_EMS_Available,
  76.   Total_EMS_Pages,
  77.   Available_EMS_Pages: Word;
  78.   Version_Number,
  79.   Pages_Number_String: ST3;
  80.   Verify: Boolean;
  81.  
  82. { * --------------------------------------------------------- * }
  83.   { The function Hex_String converts an Word into a four
  84.     character hexadecimal number(string) with leading zeroes.   }
  85.   Function Hex_String(Number: Word): ST5;
  86.     Function Hex_Char(Number: Word): Char;
  87.     Begin
  88.       If Number<10 then
  89.         Hex_Char:=Char(Number+48)
  90.       else
  91.         Hex_Char:=Char(Number+55);
  92.     end; { Function Hex_Char }
  93.  
  94.   Var
  95.     S: ST5;
  96.   Begin
  97.     S:='';
  98.     S:=Hex_Char( (Number shr 1) div 2048);
  99.     Number:=( ((Number shr 1) mod 2048) shl 1)+
  100.             (Number and 1) ;
  101.     S:=S+Hex_Char(Number div 256);
  102.     Number:=Number mod 256;
  103.     S:=S+Hex_Char(Number div 16);
  104.     Number:=Number mod 16;
  105.     S:=S+Hex_Char(Number);
  106.     Hex_String:=S+'h';
  107.   end; { Function Hex_String }
  108.  
  109. { * --------------------------------------------------------- * }
  110.  
  111.   { The function Emm_Installed checks to see if the Expanded
  112.     Memory Manager (EMM) is loaded in memory. It does this by
  113.     looking for the string 'EMMXXXX0', which should be located
  114.     at 10 bytes from the beginning of the code segment pointed
  115.     to by the EMM interrupt, 67h                                }
  116.   Function Emm_Installed: Boolean;
  117.     Var
  118.       Emm_Device_Name       : string[8];
  119.       Int_67_Device_Name    : string[8];
  120.       Position              : Word;
  121.       Regs                  : registers;
  122.  
  123.   Begin
  124.     Int_67_Device_Name:='';
  125.     Emm_Device_Name   :='EMMXXXX0';
  126.     with Regs do
  127.     Begin
  128.       { Get the code segment pointed to by Interrupt 67h, the EMM
  129.       interrupt by using DOS call $35, 'get interrupt vector'     }
  130.       AH:=$35;
  131.       AL:=EMM_INT;
  132.       Intr(DOS_int,Regs);
  133.  
  134.       { The ES pseudo-register contains the segment address pointed
  135.         to by Interrupt 67h }
  136.       { Create an 8 character string from the 8 successive bytes
  137.         pointed to by ES:$0A (10 bytes from ES)                   }
  138.       For Position:=0 to 7 do
  139.         Int_67_Device_Name:=
  140.           Int_67_Device_Name+Chr(mem[ES:Position+$0A]);
  141.       Emm_Installed:=True;
  142.       { Is it the EMM manager signature, 'EMMXXXX0'? then EMM is
  143.         installed and ready for use, if not, then the EMM manager
  144.         is not present                                            }
  145.       If Int_67_Device_Name<>Emm_Device_Name
  146.         then Emm_Installed:=False;
  147.     end; { with Regs do }
  148.   end;  { Function Emm_Installed }
  149.  
  150. { * --------------------------------------------------------- * }
  151.  
  152.   { This function returns the total number of EMS pages present
  153.     in the system, and the number of EMS pages that are
  154.     available for our use                                       }
  155.   Function EMS_Pages_Available
  156.     (Var Total_EMS_Pages,Pages_Available: Word): Word;
  157.   Var
  158.     Regs: Registers;
  159.   Begin
  160.     with Regs do
  161.     Begin
  162.       { Put the desired EMS function number in the AH pseudo-
  163.         register                                                }
  164.       AH:=Get_Unallocated_Page_Count;
  165.       intr(EMM_INT,Regs);
  166.       { The number of EMS pages available is returned in BX     }
  167.       Pages_Available:=BX;
  168.       { The total number of pages present in the system is
  169.         returned in DX                                          }
  170.       Total_EMS_Pages:=DX;
  171.       { Return the error code                                   }
  172.       EMS_Pages_Available:=AH
  173.     end;
  174.   end; { EMS_Pages_Available }
  175.  
  176. { * --------------------------------------------------------- * }
  177.  
  178.   { This function requests the desired number of pages from the
  179.     EMM                                                         }
  180.   Function Allocate_Expanded_Memory_Pages
  181.     (Pages_Needed: Word; Var Handle: Word   ): Word;
  182.   Var
  183.     Regs: Registers;
  184.   Begin
  185.     with Regs do
  186.     Begin
  187.       { Put the desired EMS function number in the AH pseudo-
  188.         register                                                }
  189.       AH:= Allocate_Pages;
  190.       { Put the desired number of pages in BX                   }
  191.       BX:=Pages_Needed;
  192.       intr(EMM_INT,Regs);
  193.       { Our EMS handle is returned in DX                        }
  194.       Handle:=DX;
  195.       { Return the error code }
  196.       Allocate_Expanded_Memory_Pages:=AH;
  197.     end;
  198.   end; { Function Allocate_Expanded_Memory_Pages }
  199.  
  200. { * --------------------------------------------------------- * }
  201.  
  202.   { This function maps a logical page onto one of the physical
  203.     pages made available to us by the
  204.     Allocate_Expanded_Memory_Pages function                     }
  205.   Function Map_Expanded_Memory_Pages
  206.     (Handle,Logical_Page,Physical_Page: Word): Word;
  207.   Var
  208.     Regs: Registers;
  209.   Begin
  210.     with Regs do
  211.     Begin
  212.       { Put the desired EMS function number in the AH pseudo-
  213.         register                                                }
  214.       AH:=Map_Pages;
  215.       { Put the physical page number to be mapped into AL       }
  216.       AL:=Physical_Page;
  217.       { Put the logical page number to be mapped in    BX       }
  218.       BX:=Logical_Page;
  219.       { Put the EMS handle assigned to us earlier in   DX       }
  220.       DX:=Handle;
  221.       Intr(EMM_INT,Regs);
  222.       { Return the error code }
  223.       Map_Expanded_Memory_Pages:=AH;
  224.     end; { with Regs do }
  225.   end; { Function Map_Expanded_Memory_Pages }
  226.  
  227. { * --------------------------------------------------------- * }
  228.  
  229.   { This function gets the physical address of the EMS page
  230.     frame we are using. The address returned is the segment
  231.     of the page frame.                                          }
  232.   Function Get_Page_Frame_Base_Address
  233.     (Var Page_Frame_Address: Word): Word;
  234.   Var
  235.     Regs: Registers;
  236.   Begin
  237.     with Regs do
  238.     Begin
  239.       { Put the desired EMS function number in the AH pseudo-
  240.         register                                                }
  241.       AH:=Get_Page_Frame;
  242.       intr(EMM_INT,Regs);
  243.       { The page frame base address is returned in BX           }
  244.       Page_Frame_Address:=BX;
  245.       { Return the error code }
  246.       Get_Page_Frame_Base_Address:=AH;
  247.      end; { Regs }
  248.   end; { Function Get_Page_Frame_Base_Address }
  249.  
  250. { * --------------------------------------------------------- * }
  251.  
  252.   { This function releases the EMS memory pages allocated to
  253.     us, back to the EMS memory pool.                            }
  254.   Function Deallocate_Expanded_Memory_Pages
  255.     (Handle: Word): Word;
  256.   Var
  257.     Regs: Registers;
  258.   Begin
  259.     with Regs do
  260.     Begin
  261.       { Put the desired EMS function number in the AH pseudo-register }
  262.       AH:=DEALLOCATE_PAGES;
  263.       { Put the EMS handle assigned to our EMS memory pages in DX }
  264.       DX:=Emm_Handle;
  265.       Intr(EMM_INT,Regs);
  266.       { Return the error code }
  267.       Deallocate_Expanded_Memory_Pages:=AH;
  268.     end; { with Regs do }
  269.   end;  { Function Deallocate_Expanded_Memory_Pages }
  270.  
  271. { * --------------------------------------------------------- * }
  272.  
  273.   { This function returns the version number of the EMM as
  274.     a 3 character string.                                       }
  275.   Function Get_Version_Number(Var Version_String: ST3): Word;
  276.   Var
  277.     Regs: Registers;
  278.     Word_Part,Fractional_Part: Char;
  279.  
  280.   Begin
  281.     with Regs do
  282.     Begin
  283.       { Put the desired EMS function number in the AH pseudo-register }
  284.       AH:=GET_VERSION;
  285.       Intr(EMM_INT,Regs);
  286.       { See if call was successful }
  287.       If AH=STATUS_OK then
  288.       Begin
  289.         { The upper four bits of AH are the Word portion of the
  290.           version number, the lower four bits are the fractional
  291.           portion. Convert the Word value to ASCII by adding 48. }
  292.         Word_Part   := Char( AL shr 4 + 48);
  293.         Fractional_Part:= Char( AL and $F +48);
  294.         Version_String:= Word_Part+'.'+Fractional_Part;
  295.       end; { If AH=STATUS_OK }
  296.       { Return the function calls error code }
  297.       Get_Version_Number:=AH;
  298.     end; { with Regs do }
  299.   end; { Function Get_Version_Number }
  300.  
  301. { * --------------------------------------------------------- * }
  302.  
  303.   { This procedure prints an error message passed by the caller,
  304.     prints the error code passed by the caller in hex, and then
  305.     terminates the program with the an error level of 1         }
  306.  
  307.   Procedure Error(Error_Message: ST80; Error_Number: Word);
  308.   Begin
  309.     Writeln(Error_Message);
  310.     Writeln('  Error_Number = ',Hex_String(Error_Number) );
  311.     Writeln('EMS test program aborting.');
  312.     Halt(1);
  313.   end; { Procedure Error_Message }
  314.  
  315. { * --------------------------------------------------------- * }
  316.  
  317. { EMS_TEST }
  318.  
  319. { This program is an example of the basic EMS functions that you
  320.   need to execute in order to use EMS memory with Turbo Pascal  }
  321.  
  322. Begin
  323.   ClrScr;
  324.  
  325.   { Determine if the Expanded Memory Manager is installed, If
  326.     not, then terminate 'main' with an ErrorLevel code of 1. }
  327.  
  328.   If not (Emm_Installed) then
  329.   Begin
  330.     Writeln('The LIM Expanded Memory Manager is not installed.');
  331.     Halt(1);
  332.   end;
  333.  
  334.   { Get the version number and display it }
  335.   Error_Code:= Get_Version_Number(Version_Number);
  336.   If Error_Code<>STATUS_OK then
  337.     Error('Error trying to get the EMS version number ',
  338.           Error_code)
  339.   else
  340.     Writeln('LIM Expanded Memory Manager, version ',
  341.             Version_Number,' is ready for use.');
  342.  
  343.   { Determine if there are enough expanded memory pages for this
  344.     application. }
  345.   Pages_Needed:=APPLICATION_PAGE_COUNT;
  346.   Error_Code:=
  347.     EMS_Pages_Available(Total_EMS_Pages,Available_EMS_Pages);
  348.   If Error_Code<>STATUS_OK then
  349.     Error('Error trying to determine the number of EMS pages available.',
  350.           Error_code);
  351.  
  352.   Writeln('There are a total of ',Total_EMS_Pages,
  353.           ' expanded memory pages present in this system.');
  354.   Writeln('  ',Available_EMS_Pages,
  355.           ' of those pages are available for your usage.');
  356.  
  357.   { If there is an insufficient number of pages for our application,
  358.     then report the error and terminate the EMS test program }
  359.   If Pages_Needed>Available_EMS_Pages then
  360.   Begin
  361.     Str(Pages_Needed,Pages_Number_String);
  362.     Error('We need '+Pages_Number_String+
  363.           ' EMS pages. There are not that many available.',
  364.           Error_Code);
  365.   end; { Pages_Needed>Available_EMS_Pages }
  366.  
  367.   { Allocate expanded memory pages for our usage }
  368.   Error_Code:= Allocate_Expanded_Memory_Pages(Pages_Needed,Emm_Handle);
  369.   Str(Pages_Needed,Pages_Number_String);
  370.   If Error_Code<>STATUS_OK then
  371.     Error('EMS test program failed trying to allocate '+Pages_Number_String+
  372.           ' pages for usage.',Error_Code);
  373.   Writeln(APPLICATION_PAGE_COUNT,
  374.           ' EMS page(s) allocated for the EMS test program.');
  375.  
  376.   { Map in the required logical pages to the physical pages
  377.     given to us, in this case just one page                     }
  378.   Physical_Page:=0;
  379. FOR Logical_Page :=0  to APPLICATION_PAGE_COUNT-1 DO BEGIN
  380.   Error_Code:=
  381.     Map_Expanded_Memory_Pages(
  382.       Emm_Handle,Logical_Page,Physical_Page);
  383.   If Error_Code<>STATUS_OK then
  384.     Error('EMS test program failed trying to map '+
  385.           'logical pages onto physical pages.',Error_Code);
  386.  
  387.   Writeln('Logical Page ',Logical_Page,
  388.           ' successfully mapped onto Physical Page ',
  389.           Physical_Page);
  390.  
  391.   { Get the expanded memory page frame address }
  392.   Error_Code:= Get_Page_Frame_Base_Address(Page_Frame_Base_Address);
  393.   If Error_Code<>STATUS_OK then
  394.     Error('EMS test program unable to get the base Page'+
  395.           ' Frame Address.',Error_Code);
  396.   Writeln('The base address of the EMS page frame is - '+
  397.           Hex_String(Page_Frame_Base_Address) );
  398.  
  399.   { Write a test pattern to expanded memory }
  400.   For Offset:=0 to 16382 do
  401.     Mem[Page_Frame_Base_Address:(Offset+Physical_Page*16384)]:=(Offset+Logical_Page) mod 256;
  402.   inc(Physical_Page);
  403.   if Physical_Page > 3 then Physical_Page:=0;
  404. END;
  405.   { Make sure that what is in EMS memory is what we just wrote }
  406.   Writeln('Testing EMS memory.');
  407.  
  408. FOR Logical_Page :=0  to APPLICATION_PAGE_COUNT-1 DO BEGIN
  409.   Error_Code:=
  410.     Map_Expanded_Memory_Pages(
  411.       Emm_Handle,Logical_Page,Physical_Page);
  412.   If Error_Code<>STATUS_OK then
  413.     Error('EMS test program failed trying to map '+
  414.           'logical pages onto physical pages.',Error_Code);
  415.   writeln('Testing P[',Physical_Page,']:L[',Logical_Page,']');
  416.   Offset:=1;
  417.   Verify:=True;
  418.   while (Offset<=16382) and (Verify=True) do
  419.   Begin
  420.     If Mem[Page_Frame_Base_Address:(Offset+Physical_Page*16384)]<>(Offset+Logical_Page) mod 256 then
  421.       Verify:=False;
  422.     Offset:=Succ(Offset);
  423.   end;  { while (Offset<=16382) and (Verify=True) }
  424.   inc(Physical_Page);
  425.   if Physical_Page > 3 then Physical_Page:=0;
  426.   If not Verify then
  427.     Error('What was written to EMS memory was not found during '+
  428.           'memory verification  test.',0);
  429. END;
  430.  
  431.   { If it isn't report the error }
  432.   Writeln('EMS memory test successful.');
  433.  
  434.   { Return the expanded memory pages given to us back to the
  435.     EMS memory pool before terminating our test program         }
  436.   Error_Code:=Deallocate_Expanded_Memory_Pages(Emm_Handle);
  437.   If Error_Code<>STATUS_OK then
  438.     Error('EMS test program was unable to deallocate '+
  439.           'the EMS pages in use.',Error_Code);
  440.   Writeln(APPLICATION_PAGE_COUNT,
  441.           ' page(s) deallocated.');
  442.   Writeln('EMS test program completed.');
  443. end.
  444.